﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using ReportWizard.Helpers;
using ReportWizard.Interface;

namespace ReportWizard.DataAccess
{
    public class WordBookmark : IBookmark, IComparer<WordBookmark>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public DateTime DateCreated { get; set; }
        public bool Deleted { get; set; }
        
        public int BookmarkGroupId { get; set; }
        public int WordTemplateId { get; set; }
        public bool IsTextBookmark { get; set; }
        public bool Visible { get; set; }

        public WordBookmark()
        {

        }

        public WordBookmark(int wordTemplateId, string name, string description, bool isTextBookmark, int bookmarkGroupId, bool visible = true)
        {
            WordTemplateId = wordTemplateId;
            Name = name;
            Description = description;
            Visible = visible;
            IsTextBookmark = isTextBookmark;
            BookmarkGroupId = bookmarkGroupId;
        }

        public void Insert()
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand saveCmd = new SqlCommand("WordBookmarkInsert", con);
                    saveCmd.CommandType = CommandType.StoredProcedure;

                    saveCmd.Parameters.Add("@WordTemplateId", SqlDbType.Int).Value = WordTemplateId;
                    saveCmd.Parameters.Add("@Name", SqlDbType.VarBinary).Value = Crypto.Encrypt(Name);
                    saveCmd.Parameters.Add("@Description", SqlDbType.VarBinary).Value =
                        Crypto.Encrypt(!string.IsNullOrEmpty(Description) ? Description : string.Empty);
                    saveCmd.Parameters.Add("@IsTextBookmark", SqlDbType.Bit).Value = IsTextBookmark;
                    saveCmd.Parameters.Add("@BookmarkGroupId", SqlDbType.Int).Value = BookmarkGroupId != 0
                                                                                                     ? BookmarkGroupId
                                                                                                     : (object)DBNull.Value;
                    saveCmd.Parameters.Add("@Visible", SqlDbType.Bit).Value = Visible;
                    saveCmd.Parameters.Add("@Id", SqlDbType.Int).Direction = ParameterDirection.Output;

                    con.Open();
                    bool isRowsAffected = saveCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        Id = Convert.ToInt32(saveCmd.Parameters["@Id"].Value);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
            }
        }

        public bool Update()
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand updCmd = new SqlCommand("WordBookmarkUpdate", con);
                    updCmd.CommandType = CommandType.StoredProcedure;

                    updCmd.Parameters.Add("@Id", SqlDbType.Int).Value = Id;
                    updCmd.Parameters.Add("@Description", SqlDbType.VarBinary).Value = Crypto.Encrypt(!string.IsNullOrEmpty(Description) ? Description : string.Empty);
                    updCmd.Parameters.Add("@IsTextBookmark", SqlDbType.Bit).Value = IsTextBookmark;
                    updCmd.Parameters.Add("@BookmarkGroupId", SqlDbType.Int).Value = BookmarkGroupId != 0
                                                                                                     ? BookmarkGroupId
                                                                                                     : (object)DBNull.Value;
                    updCmd.Parameters.Add("@Visible", SqlDbType.Bit).Value = Visible;

                    con.Open();
                    bool isRowsAffected = updCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        WordBookmark wb = Select(Id);
                        if (wb != null)
                        {
                            WordTemplate wt = WordTemplate.Select(wb.WordTemplateId);
                            if (wt != null)
                            {
                                HistoryRecord hr = new HistoryRecord
                                                       {
                                                           Action = HistoryEvent.BookmarkChange,
                                                           Description = string.Format("В шаблоне [{0}] изменено описание закладки [{1}]", wt.FileName, wb.Name)
                                                       };
                                hr.Insert();
                            }
                        }
                    }

                    return isRowsAffected;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        public static bool Delete(int id)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand delCmd = new SqlCommand("WordBookmarkDelete", con);
                    delCmd.CommandType = CommandType.StoredProcedure;

                    delCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;

                    con.Open();
                    bool isRowsAffected = delCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        WordBookmark wb = Select(id);
                        if (wb != null)
                        {
                            WordTemplate wt = WordTemplate.Select(wb.WordTemplateId);
                            if (wt != null)
                            {
                                HistoryRecord hr = new HistoryRecord
                                {
                                    Action = HistoryEvent.BookmarkChange,
                                    Description = string.Format("В шаблоне [{0}] удалена закладка [{1}]", wt.FileName, wb.Name)
                                };
                                hr.Insert();
                            }
                        }
                    }

                    return isRowsAffected;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        public static WordBookmark Select(int id)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("WordBookmarkSelect", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;

                    con.Open();
                    List<WordBookmark> cList = MapFrom(getCmd.ExecuteReader());
                    return cList != null ? cList.FirstOrDefault() : null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        public static List<WordBookmark> SelectInGroup(int bookmarkGroupId)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("WordBookmarkSelectByGroupId", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@BookmarkGroupId", SqlDbType.Int).Value = bookmarkGroupId;

                    con.Open();
                    return MapFrom(getCmd.ExecuteReader());
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        public static List<WordBookmark> Select(int wordTemplateId, bool isWithGrouped, bool isOnlyVisible = true)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("WordBookmarkSelectAll", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@WordTemplateId", SqlDbType.Int).Value = wordTemplateId;
                    getCmd.Parameters.Add("@IsOnlyVisible", SqlDbType.Bit).Value = isOnlyVisible;
                    getCmd.Parameters.Add("@IsWithGrouped", SqlDbType.Bit).Value = isWithGrouped;

                    con.Open();
                    return MapFrom(getCmd.ExecuteReader());
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static List<WordBookmark> MapFrom(SqlDataReader dr)
        {
            try
            {
                if (dr != null && dr.HasRows)
                {
                    List<WordBookmark> acList = new List<WordBookmark>();
                    while (dr.Read())
                    {
                        WordBookmark wt = new WordBookmark
                                              {
                                                  Id = Convert.ToInt32(dr["Id"]),
                                                  WordTemplateId = Convert.ToInt32(dr["WordTemplateId"]),
                                                  Name = Crypto.Decrypt((byte[]) dr["Name"]),
                                                  Description = Crypto.Decrypt((byte[]) dr["Description"]),
                                                  DateCreated = Convert.ToDateTime(dr["DateCreated"]),
                                                  IsTextBookmark = Convert.ToBoolean(dr["IsTextBookmark"]),
                                                  BookmarkGroupId = dr["BookmarkGroupId"] != DBNull.Value ? Convert.ToInt32(dr["BookmarkGroupId"]) : 0,
                                                  Visible = Convert.ToBoolean(dr["Visible"]),
                                                  Deleted = Convert.ToBoolean(dr["Deleted"])
                                              };

                        acList.Add(wt);
                    }
                    acList.Sort(new WordBookmark());
                    return acList;
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        public override string ToString()
        {
            return string.Format("Id: {0}; / Name: {1}; / Description: {2}; / Deleted: {3}; / BookmarkGroupId: {4}; / WordTemplateId: {5}; / DateCreated: {6}; / Visible: {7}; / IsTextBookmark: {8};", Id, Name, Description, Deleted, BookmarkGroupId, WordTemplateId, DateCreated.ToShortDateString(), Visible, IsTextBookmark);
        }

        public int Compare(WordBookmark x, WordBookmark y)
        {
            int isTextCompareValue = y.IsTextBookmark.CompareTo(x.IsTextBookmark);
            int groupCompareValue = x.BookmarkGroupId.CompareTo(y.BookmarkGroupId);

            if (isTextCompareValue == 0)
            {
                if (groupCompareValue == 0)
                {
                    return x.Name.CompareTo(y.Name);
                }
                else
                {
                    return groupCompareValue;
                }
            }
            else
            {
                return isTextCompareValue;
            }
        }
    }
}
